/**
 * @Author: gan
 * @Description:
 * @File:  user
 * @Version: 1.0.0
 * @Date: 2022/4/8 5:03 下午
 */

package admin

import (
	"fmt"
	"gin-canteen-src/enums"
	"gin-canteen-src/global"
	"gin-canteen-src/model/admin"
	"gin-canteen-src/model/admin/response"
	commonRequest "gin-canteen-src/model/common/request"
	commonResponse "gin-canteen-src/model/common/response"
	"gin-canteen-src/utils"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"time"
)

type UserService struct{}

// @Title  登录
// @Description  描述
// @Author gan
func (userService *UserService) Login(u *admin.User) (err error, userInter *admin.User) {
	if nil == global.GloMysql {
		return fmt.Errorf("db not init"), nil
	}
	var user admin.User
	u.Password = utils.MD5([]byte(u.Password))
	err = global.GloMysql.Where("username = ? AND password = ?", u.Username, u.Password).First(&user).Error
	return err, &user
}

// @Title 登录后生成token
// @Description  描述
// @Author gan
func (userService *UserService) MakeToken(c *gin.Context, u *admin.User) {
	j := &utils.JWT{SigningKey: []byte(global.GloConfig.JWT.SigningKey)} // 唯一签名
	claims := j.CreateClaims(commonRequest.BaseClaims{
		ID:       u.ID,
		Username: u.Username,
	})
	token, err := j.CreateToken(claims)
	if err != nil {
		global.GloLogger.Error("创建Token失败", zap.Error(err))
		commonResponse.FailWithMessage(commonResponse.ERROR, "创建Token失败", c)
		return
	}
	if !global.GloConfig.System.UseMultipoint {
		commonResponse.OkWithDetailed(response.LoginResponse{
			User:      *u,
			Token:     token,
			ExpiresAt: claims.StandardClaims.ExpiresAt * 1000,
		}, "登录成功", c)
		return
	}

	redisJWT, err := global.GloRedis.Get(c, u.Username).Result()
	if err != nil {
		global.GloLogger.Error("获取Token失败", zap.Error(err))
		commonResponse.FailWithMessage(enums.ErrorCache, "获取Token失败", c)
	}

	// jwt empty set redis
	if redisJWT == "" {
		timer := time.Duration(global.GloConfig.JWT.ExpiresTime) * time.Second
		err = global.GloRedis.Set(c, u.Username, token, timer).Err()
		if err != nil {
			global.GloLogger.Error("设置登录状态失败", zap.Error(err))
			commonResponse.FailWithMessage(enums.ErrorCache, "设置登录状态失败", c)
		}
	}

	commonResponse.OkWithDetailed(response.LoginResponse{
		User:      *u,
		Token:     token,
		ExpiresAt: claims.StandardClaims.ExpiresAt * 1000,
	}, "登录成功", c)
}

// @Title  创建账号
// @Description  描述
// @Author gan
func (userService *UserService) Create(u *admin.User) (err error, id int64) {
	if nil == global.GloMysql {
		return fmt.Errorf("db not init"), 0
	}
	u.Password = utils.MD5([]byte(u.Password))
	u.LoginAt = nil
	result := global.GloMysql.Create(&u)
	return result.Error, u.ID
}

// @Title  用户列表
// @Description  描述
// @Author gan
func (userService *UserService) GetUserList(info commonRequest.PageInfo) (list interface{}, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	db := global.GloMysql.Model(&admin.User{})
	var userList []admin.User
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Find(&userList).Error
	return userList, total, err
}

// @Title 查询用户
// @Description  描述
// @Author gan
func (userService *UserService) FindUserById(id int64) (user *admin.User, err error) {
	var u admin.User
	err = global.GloMysql.Where("`id` = ?", id).First(&u).Error
	return &u, err
}

// @Title  重置密码
// @Description  描述
// @Author gan
func (userService *UserService) ResetPassword(ID uint) (err error) {
	err = global.GloMysql.Model(&admin.User{}).Where("id = ?", ID).Update("password", utils.MD5([]byte("123456"))).Error
	return err
}
